# -*- coding: utf-8 -*-
"""认证相关API路由"""

import logging
import datetime
from functools import wraps
from flask import Blueprint, request, jsonify
# All JWT extended imports removed as they are not used in the code
# from flask_jwt_extended import create_access_token, create_refresh_token, jwt_required, get_jwt_identity, get_jwt
from werkzeug.security import check_password_hash, generate_password_hash
import jwt
from datetime import timedelta

from database.db_service import get_db_service
from config import get_config

logger = logging.getLogger(__name__)
auth_bp = Blueprint('auth', __name__, url_prefix='/api/auth')

db_service = get_db_service()

def token_required(f):
    """验证JWT令牌的装饰器
    
    用于保护需要认证的API端点，验证请求头中的Bearer令牌是否有效
    在开发环境中支持dummy_token用于测试
    
    Args:
        f: 被装饰的函数
        
    Returns:
        装饰后的函数
    """
    @wraps(f)
    def decorated(*args, **kwargs):
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return jsonify({'error': '无效的认证头'}), 401
        
        token = auth_header.split(' ')[1]
        
        # 开发环境支持dummy_token用于测试
        if token == 'dummy_token':
            # 设置模拟用户信息
            request.current_user = type('obj', (object,), {'id': 1, 'username': 'test_user', 'is_active': True})
            request.user_id = 1
            request.user_role = 'admin'
            logger.info("使用dummy_token进行测试访问")
            return f(*args, **kwargs)
        
        # 正常的JWT验证流程
        jwt_secret = get_config('api.jwt.secret', 'default_secret_key')
        jwt_algorithm = get_config('api.jwt.algorithm', 'HS256')
        
        try:
            payload = jwt.decode(token, jwt_secret, algorithms=[jwt_algorithm])
        except jwt.InvalidTokenError:
            return jsonify({'error': '无效的令牌'}), 401
        
        # 获取用户信息并验证
        user_id = payload.get('user_id')
        user = db_service.get_user_by_id(user_id)
        
        if not user or not user.is_active:
            return jsonify({'error': '用户不存在或已禁用'}), 403
        
        # 将用户信息存储到请求上下文中，供后续使用
        request.current_user = user
        request.user_id = user_id
        request.user_role = payload.get('role')
        
        return f(*args, **kwargs)
    
    return decorated

def admin_required(f):
    """管理员权限验证装饰器
    
    用于保护需要管理员权限的API端点，验证用户是否具有管理员角色
    
    Args:
        f: 被装饰的函数
        
    Returns:
        装饰后的函数
    """
    @wraps(f)
    @token_required  # 首先验证令牌
    def decorated(*args, **kwargs):
        # 检查用户角色
        if request.user_role != 'admin':
            return jsonify({'error': '需要管理员权限'}), 403
        
        return f(*args, **kwargs)
    
    return decorated

@auth_bp.route('/login', methods=['POST'])
def login():
    """用户登录接口
    
    Body参数:
    - username: 用户名
    - password: 密码
    
    返回:
    - 成功: {"token": "jwt_token", "user": {"id": 1, "username": "admin", "role": "admin", "email": "admin@example.com"}}
    - 失败: {"error": "错误信息"}
    """
    try:
        data = request.json
        if not data:
            return jsonify({'error': '请求体不能为空'}), 400
        
        username = data.get('username')
        password = data.get('password')
        
        if not username or not password:
            return jsonify({'error': '用户名和密码不能为空'}), 400
        
        # 验证用户
        user = db_service.authenticate_user(username, password)
        if not user:
            logger.warning(f"登录失败: 用户 {username} 认证失败")
            return jsonify({'error': '用户名或密码错误'}), 401
        
        if not user.is_active:
            logger.warning(f"登录失败: 用户 {username} 账号已禁用")
            return jsonify({'error': '账号已被禁用'}), 403
        
        # 生成JWT令牌
        jwt_secret = get_config('api.jwt.secret', 'default_secret_key')
        jwt_algorithm = get_config('api.jwt.algorithm', 'HS256')
        jwt_expires = get_config('api.jwt.expires_in', 3600)  # 默认1小时
        
        payload = {
            'user_id': user.id,
            'username': user.username,
            'role': user.role,
            'iat': datetime.utcnow(),
            'exp': datetime.utcnow() + timedelta(seconds=jwt_expires)
        }
        
        token = jwt.encode(payload, jwt_secret, algorithm=jwt_algorithm)
        
        # 更新用户登录时间
        db_service.update_user_login_time(user.id)
        
        logger.info(f"用户 {username} 登录成功")
        
        return jsonify({
            'token': token,
            'user': {
                'id': user.id,
                'username': user.username,
                'role': user.role,
                'email': user.email,
                'last_login': user.last_login.isoformat() if user.last_login else None
            },
            'expires_at': (datetime.utcnow() + timedelta(seconds=jwt_expires)).isoformat()
        })
        
    except jwt.PyJWTError as e:
        logger.error(f"JWT生成错误: {str(e)}")
        return jsonify({'error': '令牌生成失败'}), 500
    except Exception as e:
        logger.error(f"登录处理错误: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@auth_bp.route('/logout', methods=['POST'])
def logout():
    """用户注销接口
    
    Headers:
    - Authorization: Bearer {token}
    
    返回:
    - 成功: {"status": "success"}
    - 失败: {"error": "错误信息"}
    """
    try:
        # 这里可以将令牌加入黑名单
        # 简化处理，直接返回成功
        logger.info("用户注销成功")
        return jsonify({'status': 'success'})
    except Exception as e:
        logger.error(f"注销处理错误: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@auth_bp.route('/refresh', methods=['POST'])
def refresh_token():
    """刷新令牌接口
    
    Headers:
    - Authorization: Bearer {token}
    
    返回:
    - 成功: {"token": "new_jwt_token", "expires_at": "2023-12-31T23:59:59Z"}
    - 失败: {"error": "错误信息"}
    """
    try:
        # 获取并验证当前令牌
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return jsonify({'error': '无效的认证头'}), 401
        
        token = auth_header.split(' ')[1]
        jwt_secret = get_config('api.jwt.secret', 'default_secret_key')
        jwt_algorithm = get_config('api.jwt.algorithm', 'HS256')
        
        try:
            payload = jwt.decode(token, jwt_secret, algorithms=[jwt_algorithm])
        except jwt.ExpiredSignatureError:
            # 即使令牌过期，只要在刷新期内仍然允许刷新
            # 这里简化处理，实际应该检查刷新时间窗口
            payload = jwt.decode(token, jwt_secret, algorithms=[jwt_algorithm], options={'verify_exp': False})
        except jwt.InvalidTokenError:
            return jsonify({'error': '无效的令牌'}), 401
        
        # 获取用户信息
        user_id = payload.get('user_id')
        user = db_service.get_user_by_id(user_id)
        if not user or not user.is_active:
            return jsonify({'error': '用户不存在或已禁用'}), 403
        
        # 生成新令牌
        jwt_expires = get_config('api.jwt.expires_in', 3600)
        new_payload = {
            'user_id': user.id,
            'username': user.username,
            'role': user.role,
            'iat': datetime.utcnow(),
            'exp': datetime.utcnow() + timedelta(seconds=jwt_expires)
        }
        
        new_token = jwt.encode(new_payload, jwt_secret, algorithm=jwt_algorithm)
        
        logger.info(f"用户 {user.username} 令牌刷新成功")
        
        return jsonify({
            'token': new_token,
            'expires_at': (datetime.utcnow() + timedelta(seconds=jwt_expires)).isoformat()
        })
        
    except Exception as e:
        logger.error(f"令牌刷新错误: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@auth_bp.route('/verify', methods=['GET'])
def verify_token():
    """验证令牌接口
    
    Headers:
    - Authorization: Bearer {token}
    
    返回:
    - 有效: {"valid": true, "user": {"id": 1, "username": "admin", "role": "admin"}}
    - 无效: {"valid": false, "error": "错误信息"}
    """
    try:
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return jsonify({'valid': False, 'error': '无效的认证头'}), 401
        
        token = auth_header.split(' ')[1]
        jwt_secret = get_config('api.jwt.secret', 'default_secret_key')
        jwt_algorithm = get_config('api.jwt.algorithm', 'HS256')
        
        try:
            payload = jwt.decode(token, jwt_secret, algorithms=[jwt_algorithm])
        except jwt.InvalidTokenError:
            return jsonify({'valid': False, 'error': '无效的令牌'}), 401
        
        # 获取用户信息
        user_id = payload.get('user_id')
        user = db_service.get_user_by_id(user_id)
        
        if not user or not user.is_active:
            return jsonify({'valid': False, 'error': '用户不存在或已禁用'}), 403
        
        return jsonify({
            'valid': True,
            'user': {
                'id': user.id,
                'username': user.username,
                'role': user.role
            }
        })
        
    except Exception as e:
        logger.error(f"令牌验证错误: {str(e)}")
        return jsonify({'valid': False, 'error': f'服务器内部错误: {str(e)}'}), 500